#include <memory>
#include "Log.hpp"
#include "Socket.hpp"
#include "epoll.hpp"


static const int default_port = 8080;
static const int max_events = 1024;

class EpollServer
{
public:
    EpollServer() 
    : _sock(std::make_unique<TcpSocket>()),
      _isrunning(false),
      _epoll(new Epoll())
    {}

    ~EpollServer()
    {
        delete _epoll;
    }

    void InitServer(int port = default_port)
    {
        _sock->BulidListenSocket(port);
        ILOG("创建监听套接字成功 ...");
        _epoll->InitEpoll();
        ILOG("初始化epoll成功 ...");
        // 注册监听套接字的读事件
        _epoll->AddEvent(_sock->GetSocket(), EPOLLIN);
    }

    void Handler(int n)
    {
        for(int i = 0; i < n; i++)
        {
            if(_ev[i].events & EPOLLIN)
            {
                // 监听套接字读事件就绪
                if(_ev[i].data.fd == _sock->GetSocket())
                {
                    std::string peerip;
                    int peerport;
                    int newfd = _sock->AcceptSocket(&peerip, &peerport);
                    ILOG("获取新连接, ip: %s, port: %d", peerip.c_str(), peerport);
                    _epoll->AddEvent(newfd, EPOLLIN);
                }
                // 普通文件描述符
                else
                {
                    char buffer[1024];
                    int fd = _ev[i].data.fd;
                    int ret = recv(fd, buffer, sizeof(buffer) - 1, 0); // 读取有问题
                    if(ret > 0)
                    {
                        buffer[ret] = '\0';
                        std::cout << "client echo# " << buffer << std::endl;
                        std::string str = "server echo# ";
                        str += buffer;
                        send(fd, str.c_str(), str.size(), 0);
                    }
                    else
                    {
                        if(ret == 0)
                        {
                            ILOG("client close ...");
                        }
                        else
                        {
                            ELOG("recv error ...");
                        }
                        // 先调用DelEvent后才能close，因为epoll_ctl只处理有效的fd
                        _epoll->DelEvent(fd);
                        close(fd);
                    }
                }
            }
            
        }
    }

    void Loop()
    {
        _isrunning = true;
        int timeout = 1000;
        while(_isrunning)
        {
            int n = _epoll->Wait(_ev, max_events, timeout);
            switch(n)
            {
                case -1:
                    ELOG("Wait error ...");
                    break;
                case 0:
                    // DLOG("Wait timeout ...");
                    break;
                default:
                    // DLOG("Wait success ...");
                    Handler(n);
                    break;
            }
        }
        _isrunning = false;
    }
    void Stop()
    {
        _isrunning = false;
    }

private:
    std::unique_ptr<Socket> _sock;
    bool _isrunning;
    Epoll *_epoll;
    struct epoll_event _ev[max_events];
};